package com.yueyang.sojourn.server.service.sojourn.merch;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yueyang.sojourn.server.common.baymax.web.result.JAssert;
import com.yueyang.sojourn.server.model.enums.MerchSaleTypeEnum;
import com.yueyang.sojourn.server.model.enums.ShelfStatusEnum;
import com.yueyang.sojourn.server.model.po.SojournMerch;
import com.yueyang.sojourn.server.model.vo.SojournMerchPriceCalculateVo;
import com.yueyang.sojourn.server.model.vo.SojournMerchVo;
import com.yueyang.sojourn.server.service.attachdetail.AttachDetailService;
import com.yueyang.sojourn.server.service.sojourn.collect.SojournMerchCollectService;
import com.yueyang.sojourn.server.service.sojourn.project.ReadProjectService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yemingxing
 * @summary 只读 service
 * @Copyright (c) 2020, Yueyang Group All Rights Reserved.
 * @since 2020-02-18 23:38
 */
@Service
public class ReadMerchService {

    @Autowired
    private SojournMerchService sojournMerchService;
    @Autowired
    private AttachDetailService attachDetailService;
    @Autowired
    private ReadProjectService readProjectService;
    @Autowired
    private SojournMerchCollectService collectService;

    /**
     * @param loginUserId 登录ucid
     * @param keyWord     标题关键词
     * @param projectId   所属项目id
     * @param shelfStatus 上架状态{@link ShelfStatusEnum#values()}
     * @param pageNo      页码
     * @param pageSize    页大小
     * @return com.github.pagehelper.PageInfo<com.yueyang.sojourn.server.model.vo.SojournMerchVo>
     * @author yemingxing
     * @summary 列表分页查询
     * @version v1
     * @since 2020-02-19
     */
    public PageInfo<SojournMerchVo> findPage(long loginUserId, String keyWord, Long projectId, Integer shelfStatus, int pageNo, int pageSize) {
        // todo-ymx 关键词搜索 like
        PageInfo<SojournMerch> pageInfo = PageHelper.startPage(pageNo, pageSize)
                .doSelectPageInfo(() -> sojournMerchService.findBy(keyWord, projectId, Optional.ofNullable(shelfStatus).map(Collections::singletonList).orElse(null)));

        PageInfo<SojournMerchVo> voPageInfo = new PageInfo<>();
        BeanUtils.copyProperties(pageInfo, voPageInfo);
        voPageInfo.setList(pageInfo.getList().parallelStream()
                .map(this::po2vo)
                .collect(Collectors.toList()));
        return voPageInfo;
    }

    /**
     * @param projectId   所属项目id
     * @param shelfStatus 上架状态{@link ShelfStatusEnum#values()}
     * @param pageNo      页码
     * @param pageSize    页大小
     * @return com.github.pagehelper.PageInfo<com.yueyang.sojourn.server.model.vo.SojournMerchVo>
     * @author yemingxing
     * @summary 精选商品分页查询
     * @version v1
     * @since 2020-02-19
     */
    public PageInfo<SojournMerchVo> findWxPage(Long projectId, Integer shelfStatus, int pageNo, int pageSize) {
        PageInfo<SojournMerch> pageInfo = PageHelper.startPage(pageNo, pageSize)
                .doSelectPageInfo(() -> sojournMerchService.findBy(null, projectId, Optional.ofNullable(shelfStatus).map(Collections::singletonList).orElse(null)));

        PageInfo<SojournMerchVo> voPageInfo = new PageInfo<>();
        BeanUtils.copyProperties(pageInfo, voPageInfo);
        voPageInfo.setList(pageInfo.getList().parallelStream()
                .map(po -> po2vo(po, MerchVoType.MERCH_PIC))
                .collect(Collectors.toList()));
        return voPageInfo;
    }

    private SojournMerchVo po2vo(SojournMerch merch, MerchVoType... voType) {
        SojournMerchVo vo = new SojournMerchVo();
        BeanUtils.copyProperties(merch, vo);
        // vip 价格默认95折，并且个位数进一位
        vo.setVipPrice(this.getFinalPirce(BigDecimal.valueOf(merch.getPrice()), MerchSaleTypeEnum.VIP).intValue());
        vo.setSales(JSON.parseArray(merch.getSale(), Integer.class));
        List<MerchVoType> voTypes = Arrays.asList(voType);
        if (CollectionUtils.isEmpty(voTypes) || voTypes.contains(MerchVoType.MERCH_PIC)) {
            vo.setMerchPic(attachDetailService.selectListByMerchId(merch.getId()));
        }
        if (CollectionUtils.isEmpty(voTypes) || voTypes.contains(MerchVoType.RELATE_PROJECT)) {
            vo.setSojournProject(readProjectService.selectVoByPrimaryKey(merch.getProjectId(), ReadProjectService.ProjectVoType.GEO_LOCATION));
        }

        return vo;
    }

    public List<SojournMerchVo> findVoByLayoutId(int layoutId, Integer shelfStatus) {
        List<SojournMerch> merchList = sojournMerchService.findByLayoutId(layoutId, shelfStatus);
        return merchList.parallelStream().map(po -> this.po2vo(po, MerchVoType.MERCH_PIC)).collect(Collectors.toList());
    }

    public enum MerchVoType {
        /**
         * vo转换指定所需字段
         */
        MERCH_PIC,
        RELATE_PROJECT;
    }

    public SojournMerchVo findVoById(Long merchId) {
        SojournMerch sojournMerch = sojournMerchService.selectByPrimaryKey(merchId);
        return po2vo(sojournMerch);
    }

    public SojournMerchVo findWxVoById(Long merchId, Long userId) {
        SojournMerch sojournMerch = sojournMerchService.selectByPrimaryKey(merchId);
        SojournMerchVo vo = po2vo(sojournMerch);

        if (userId != null) {
            vo.setCollected(collectService.findByMerchIdAndUserId(merchId, userId) != null);
        }
        // 未登录，收藏状态默认为false
        else {
            vo.setCollected(false);
        }

        return vo;
    }


    public boolean isMerchAvailable(long loginUserId, Long merchId) {
        SojournMerch sojournMerch = sojournMerchService.selectByPrimaryKey(merchId);
        if (Objects.isNull(sojournMerch)) {
            JAssert.justFailed("商品不存在");
        }

        return DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH).after(sojournMerch.getAvailableDateEnd());
    }


    public PageInfo<SojournMerchVo> findCollectPage(Long userId, int pageNum, int pageSize) {
        PageInfo<SojournMerch> pageInfo = PageHelper.startPage(pageNum, pageSize)
                .doSelectPageInfo(() -> this.sojournMerchService.findCollectList(userId));
        PageInfo<SojournMerchVo> voPageInfo = new PageInfo<>();
        BeanUtils.copyProperties(pageInfo, voPageInfo);
        voPageInfo.setList(pageInfo.getList().parallelStream()
                .map(po -> po2vo(po, MerchVoType.MERCH_PIC))
                .collect(Collectors.toList()));
        return voPageInfo;
    }

    /**
     * todo 后期修改成真实的计算方式，以及用策略模式
     * 获取vip价格
     *
     * @return
     */
    public BigDecimal getFinalPirce(BigDecimal price, MerchSaleTypeEnum... saleTypeEnums) {
        BigDecimal rs = price;
        if (saleTypeEnums == null || saleTypeEnums.length <= 0) {
            return rs;
        }
        for (MerchSaleTypeEnum saleTypeEnum : saleTypeEnums) {
            if (saleTypeEnum.equals(MerchSaleTypeEnum.VIP)) {
                rs = price.multiply(new BigDecimal(0.95)).setScale(0, RoundingMode.CEILING);
            } else {
                // todo 其它
            }
        }
        return rs;
    }

    /**
     * 获取：按商品优惠和用户情况获取商品的优惠策略
     *
     * @param sales
     * @param memberFlag
     * @return
     */
    public List<MerchSaleTypeEnum> getMerchRealSales(List<Integer> sales, boolean memberFlag) {
        List<MerchSaleTypeEnum> currentMerchSales = new ArrayList<>();
        for (Integer sale : sales) {
            if (sale.equals(MerchSaleTypeEnum.VIP.getCode()) && !memberFlag) {
                continue;
            } else {
                for (MerchSaleTypeEnum saleTypeEnum : MerchSaleTypeEnum.values()) {
                    if (saleTypeEnum.getCode() == sale) {
                        currentMerchSales.add(saleTypeEnum);
                    }
                }
            }
        }
        return currentMerchSales;
    }

    /**
     * 计算符合的优惠策略:1 如果指定了策略，直接使用指定策略计算； 如果没有指定策略，则使用商品本身策略计算
     *
     * @param merch
     * @param count
     * @param memberFlag
     * @return
     */
    public SojournMerchPriceCalculateVo calculateMerchPrice(SojournMerch merch, Integer count, List<MerchSaleTypeEnum> merchSales, boolean memberFlag) {

        //计算符合的优惠策略:1 如果指定了策略，直接使用指定策略计算； 如果没有指定策略，则使用商品本身策略计算
        List<MerchSaleTypeEnum> currentMerchSales = new ArrayList<>();
        if (merchSales != null && !merchSales.isEmpty()) {
            currentMerchSales.addAll(merchSales);
        } else {
            currentMerchSales.addAll(getMerchRealSales(JSON.parseArray(merch.getSale(), Integer.class), memberFlag));
        }

        BigDecimal originalOnePrice = new BigDecimal(merch.getPrice());//原始单价
        BigDecimal finalOnePrice = null;//最终单价
        BigDecimal totalOriginalPrice = originalOnePrice.multiply(new BigDecimal(count));//原始总价
        BigDecimal totalFinalPrice = null;//最终最价
        BigDecimal totalDiscountedPrice = null; //已优惠的价钱
        if (currentMerchSales == null || currentMerchSales.isEmpty()) {
            finalOnePrice = originalOnePrice;
        } else {
            MerchSaleTypeEnum[] temp = new MerchSaleTypeEnum[currentMerchSales.size()];
            currentMerchSales.toArray(temp);
            finalOnePrice = getFinalPirce(originalOnePrice, temp);
        }

        totalFinalPrice = finalOnePrice.multiply(new BigDecimal(count));
        totalDiscountedPrice = totalOriginalPrice.subtract(totalFinalPrice);

        SojournMerchPriceCalculateVo vo = new SojournMerchPriceCalculateVo();
        vo.setOriginalOnePrice(originalOnePrice);
        vo.setDiscountOnePrice(finalOnePrice);
        vo.setOriginalPrice(totalOriginalPrice);
        vo.setDiscountedPrice(totalDiscountedPrice);
        vo.setFinalPrice(totalFinalPrice);
        return vo;
    }

    /**
     * 计算符合的优惠策略:1 如果指定了策略，直接使用指定策略计算； 如果没有指定策略，则使用商品本身策略计算
     *
     * @param merchId
     * @param count
     * @param memberFlag
     * @return
     */
    public SojournMerchPriceCalculateVo calculateMerchPrice(Long merchId, Integer count, List<MerchSaleTypeEnum> merchSales, boolean memberFlag) {
        SojournMerch merch = sojournMerchService.selectByPrimaryKey(merchId);
        if (merch == null) {
            return null;
        }
        return calculateMerchPrice(merch, count, merchSales, memberFlag);
    }
}
